home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / edit.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  11KB  |  446 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. /* Close approximation of the mailx(1) builtin editor for sending mail. */
  20.  
  21. #include "mutt.h"
  22. #include "mutt_curses.h"
  23. #include "send.h"
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include <errno.h>
  32.  
  33. /*
  34.  * SLcurses_waddnstr() can't take a "const char *", so this is only
  35.  * declared "static" (sigh)
  36.  */
  37. static char EditorHelp[] = "\
  38. ~~        insert a line begining with a single ~\n\
  39. ~b users    add users to the Bcc: field\n\
  40. ~c users    add users to the Cc: field\n\
  41. ~f messages    include messages\n\
  42. ~F messages    same as ~f, except also include headers\n\
  43. ~h        edit the message header\n\
  44. ~m messages    include and quote messages\n\
  45. ~M messages    same as ~m, except include headers\n\
  46. ~p        print the message\n\
  47. ~q        write file and quit editor\n\
  48. ~r file        read a file into the editor\n\
  49. ~t users    add users to the To: field\n\
  50. ~u        recall the previous line\n\
  51. ~v        edit message with the $visual editor\n\
  52. ~w file        write message to file\n\
  53. ~x        abort changes and quit editor\n\
  54. ~?        this message\n\
  55. .        on a line by itself ends input\n";
  56.  
  57. static char **
  58. be_snarf_data (FILE *f, char **buf, int *bufmax, int *buflen, int offset,
  59.            int bytes, int prefix)
  60. {
  61.   char tmp[HUGE_STRING];
  62.   char *p = tmp;
  63.   int tmplen = sizeof (tmp);
  64.  
  65.   tmp[sizeof (tmp) - 1] = 0;
  66.   if (prefix)
  67.   {
  68.     strfcpy (tmp, Prefix, sizeof (tmp));
  69.     tmplen = strlen (tmp);
  70.     p = tmp + tmplen;
  71.     tmplen = sizeof (tmp) - tmplen;
  72.   }
  73.  
  74.   fseek (f, offset, 0);
  75.   while (bytes > 0)
  76.   {
  77.     if (fgets (p, tmplen - 1, f) == NULL) break;
  78.     bytes -= strlen (p);
  79.     if (*bufmax == *buflen)
  80.       safe_realloc ((void **)&buf, sizeof (char *) * (*bufmax += 25));
  81.     buf[(*buflen)++] = safe_strdup (tmp);
  82.   }
  83.   if (buf) buf[*buflen] = NULL;
  84.   return (buf);
  85. }
  86.  
  87. static char **
  88. be_snarf_file (const char *path, char **buf, int *max, int *len)
  89. {
  90.   FILE *f;
  91.   struct stat sb;
  92.   
  93.   if ((f = fopen (path, "r")))
  94.   {
  95.     fstat (fileno (f), &sb);
  96.     buf = be_snarf_data (f, buf, max, len, 0, sb.st_size, 0);
  97.     fclose (f);
  98.   }
  99.   return (buf);
  100. }
  101.  
  102. static int be_barf_file (const char *path, char **buf, int buflen)
  103. {
  104.   FILE *f;
  105.   int i;
  106.   
  107.   if ((f = fopen (path, "w")) == NULL)
  108.   {
  109.     addstr (strerror (errno));
  110.     addch ('\n');
  111.     return (-1);
  112.   }
  113.   for (i = 0; i < buflen; i++) fputs (buf[i], f);
  114.   if (fclose (f) == 0) return 0;
  115.   printw ("fclose: %s\n", strerror (errno));
  116.   return (-1);
  117. }
  118.  
  119. static void be_free_memory (char **buf, int buflen)
  120. {
  121.   while (buflen-- > 0)
  122.     free (buf[buflen]);
  123.   if (buf)
  124.     free (buf);
  125. }
  126.  
  127. static char **
  128. be_include_messages (char *msg, char **buf, int *bufmax, int *buflen,
  129.              int pfx, int inc_hdrs)
  130. {
  131.   int offset, bytes, n;
  132.   char tmp[LONG_STRING];
  133.  
  134.   while ((msg = strtok (msg, " ,")) != NULL)
  135.   {
  136.     n = atoi (msg);
  137.     if (n > 0 && n <= Context->msgcount)
  138.     {
  139.       n--;
  140.  
  141.       /* add the attribution */
  142.       mutt_make_string (tmp, sizeof (tmp)-1, Attribution, Context->hdrs[n]);
  143.       strcat (tmp, "\n");
  144.  
  145.       if (*bufmax == *buflen)
  146.     safe_realloc ((void **)&buf, sizeof (char *) * (*bufmax += 25));
  147.       buf[(*buflen)++] = safe_strdup (tmp);
  148.  
  149.       bytes = Context->hdrs[n]->content->length;
  150.       if (inc_hdrs)
  151.       {
  152.     offset = Context->hdrs[n]->offset;
  153.     bytes += Context->hdrs[n]->content->offset - offset;
  154.       }
  155.       else
  156.     offset = Context->hdrs[n]->content->offset;
  157.       buf = be_snarf_data (Context->fp, buf, bufmax, buflen, offset, bytes,
  158.                pfx);
  159.  
  160.       if (*bufmax == *buflen)
  161.     safe_realloc ((void **)&buf, sizeof (char *) * (*bufmax += 25));
  162.       buf[(*buflen)++] = safe_strdup ("\n");
  163.     }
  164.     else
  165.       printw ("%d: invalid message number.\n", n);
  166.     msg = NULL;
  167.   }
  168.   return (buf);
  169. }
  170.  
  171. static void be_print_header (ENVELOPE *env)
  172. {
  173.   char tmp[HUGE_STRING];
  174.  
  175.   if (env->to)
  176.   {
  177.     addstr ("To: ");
  178.     tmp[0] = 0;
  179.     rfc822_write_address (tmp, sizeof (tmp), env->to);
  180.     addstr (tmp);
  181.     addch ('\n');
  182.   }
  183.   if (env->cc)
  184.   {
  185.     addstr ("Cc: ");
  186.     tmp[0] = 0;
  187.     rfc822_write_address (tmp, sizeof (tmp), env->cc);
  188.     addstr (tmp);
  189.     addch ('\n');
  190.   }
  191.   if (env->bcc)
  192.   {
  193.     addstr ("Bcc: ");
  194.     tmp[0] = 0;
  195.     rfc822_write_address (tmp, sizeof (tmp), env->bcc);
  196.     addstr (tmp);
  197.     addch ('\n');
  198.   }
  199.   if (env->subject)
  200.   {
  201.     addstr ("Subject: ");
  202.     addstr (env->subject);
  203.     addch ('\n');
  204.   }
  205.   addch ('\n');
  206. }
  207.  
  208. /* args:
  209.  *    force    override the $ask* vars (used for the ~h command)
  210.  */
  211. static void be_edit_header (ENVELOPE *e, int force)
  212. {
  213.   char tmp[HUGE_STRING];
  214.  
  215.   move (LINES-1, 0);
  216.  
  217.   addstr ("To: ");
  218.   tmp[0] = 0;
  219.   rfc822_write_address (tmp, sizeof (tmp), e->to);
  220.   if (!e->to || force)
  221.   {
  222.     if (mutt_enter_string ((unsigned char *) tmp, sizeof (tmp), LINES-1, 4, 0) == 0)
  223.     {
  224.       mutt_free_address (&e->to);
  225.       mutt_parse_adrlist (&e->to, tmp, "@");
  226.       e->to = mutt_expand_aliases (e->to);
  227.       tmp[0] = 0;
  228.       rfc822_write_address (tmp, sizeof (tmp), e->to);
  229.       mvaddstr (LINES - 1, 4, tmp);
  230.     }
  231.   }
  232.   else
  233.   {
  234.     addstr (tmp);
  235.   }
  236.   addch ('\n');
  237.  
  238.   if (!e->subject || force)
  239.   {
  240.     addstr ("Subject: ");
  241.     strfcpy (tmp, e->subject ? e->subject: "", sizeof (tmp));
  242.     if (mutt_enter_string ((unsigned char *) tmp, sizeof (tmp), LINES-1, 9, 0) == 0)
  243.     {
  244.       safe_free ((void **) &e->subject);
  245.       e->subject = safe_strdup (tmp);
  246.     }
  247.     addch ('\n');
  248.   }
  249.  
  250.   if ((!e->cc && option (OPTASKCC)) || force)
  251.   {
  252.     addstr ("Cc: ");
  253.     tmp[0] = 0;
  254.     rfc822_write_address (tmp, sizeof (tmp), e->cc);
  255.     if (mutt_enter_string ((unsigned char *) tmp, sizeof (tmp), LINES-1, 4, 0) == 0)
  256.     {
  257.       mutt_free_address (&e->cc);
  258.       mutt_parse_adrlist (&e->cc, tmp, "@");
  259.       e->cc = mutt_expand_aliases (e->cc);
  260.       tmp[0] = 0;
  261.       rfc822_write_address (tmp, sizeof (tmp), e->cc);
  262.       mvaddstr (LINES - 1, 4, tmp);
  263.     }
  264.     addch ('\n');
  265.   }
  266.  
  267.   if (option (OPTASKBCC) || force)
  268.   {
  269.     addstr ("Bcc: ");
  270.     tmp[0] = 0;
  271.     rfc822_write_address (tmp, sizeof (tmp), e->bcc);
  272.     if (mutt_enter_string ((unsigned char *) tmp, sizeof (tmp), LINES-1, 5, 0) == 0)
  273.     {
  274.       mutt_free_address (&e->bcc);
  275.       mutt_parse_adrlist (&e->bcc, tmp, "@");
  276.       e->bcc = mutt_expand_aliases (e->bcc);
  277.       tmp[0] = 0;
  278.       rfc822_write_address (tmp, sizeof (tmp), e->bcc);
  279.       mvaddstr (LINES - 1, 5, tmp);
  280.     }
  281.     addch ('\n');
  282.   }
  283. }
  284.  
  285. int mutt_builtin_editor (const char *path, HEADER *msg, HEADER *cur)
  286. {
  287.   char **buf = NULL;
  288.   int bufmax = 0, buflen = 0;
  289.   char tmp[LONG_STRING];
  290.   int abort = 0;
  291.   int done = 0;
  292.   int i;
  293.   char *p;
  294.   
  295.   scrollok (stdscr, TRUE);
  296.  
  297.   be_edit_header (msg->env, 0);
  298.  
  299.   addstr ("(End message with a . on a line by itself)\n");
  300.  
  301.   buf = be_snarf_file (path, buf, &bufmax, &buflen);
  302.  
  303.   tmp[0] = 0;
  304.   while (!done)
  305.   {
  306.     if (mutt_enter_string ((unsigned char *) tmp, sizeof (tmp), LINES-1, 0, 0) == -1)
  307.     {
  308.       tmp[0] = 0;
  309.       continue;
  310.     }
  311.     addch ('\n');
  312.  
  313.     if (tmp[0] == EscChar[0] && tmp[1] != EscChar[0])
  314.     {
  315.       /* remove trailing whitespace from the line */
  316.       p = tmp + strlen (tmp) - 1;
  317.       while (p >= tmp && ISSPACE (*p))
  318.     *p-- = 0;
  319.  
  320.       p = tmp + 2;
  321.       SKIPWS (p);
  322.  
  323.       switch (tmp[1])
  324.       {
  325.     case '?':
  326.       addstr (EditorHelp);
  327.       break;
  328.     case 'b':
  329.       mutt_parse_adrlist (&msg->env->bcc, p, "@");
  330.       msg->env->bcc = mutt_expand_aliases (msg->env->bcc);
  331.       break;
  332.     case 'c':
  333.       mutt_parse_adrlist (&msg->env->cc, p, "@");
  334.       msg->env->cc = mutt_expand_a